Appearance
一、基础概念
梳理一下 关于 SpringBean 生命周期的一些概念和理解。
Spring Bean 指的是Spring 容器中的对象,这里讲述 Bean 的生命周期一般指的是 单例 Bean。
Spring Bean 的四个阶段
如果只是讲述四个笼统的阶段,那么Spring Bean 的生命周期可以分为:实例化 Instantiation → 属性赋值 Populate → 初始化 Initialization → 销毁 Destruction。
一般而言,Spring Bean 在初始化完成之后,就代表这个Bean 在容器中是可用的。
在面试题中,有可能有问一下普通的 Java 对象 和 Spring Bean 对象的生命周期的区别。
可以看一下下面这个回答:
普通Java对象的生命周期是由Java语言规则控制的,从对象的创建(实例化)开始,到被垃圾回收器回收结束。对象的创建和销毁非常直接,与对象引用的存在时间直接相关。
Spring Bean的生命周期更为复杂,因为Spring框架控制着Bean的整个生命周期。这包括了Bean的创建、初始化后的处理、以及销毁前的处理。Spring通过依赖注入管理Bean的属性,还可以通过实现特定的接口或配置声明周期回调方法来在Bean的生命周期的不同阶段执行特定的操作。这为在Bean创建和销毁过程中加入自定义逻辑提供了机会。
// 普通Java对象生命周期:
// 1. 声明: MyClass obj;
// 2. 实例化: obj = new MyClass();
// 3. 使用: obj.method();
// 4. 垃圾回收: 不再有引用指向obj时,由垃圾回收器回收
// Spring Bean生命周期:
// 1. 实例化Bean
// 2. 设置Bean属性
// 3. 如果Bean实现了BeanNameAware接口, 调用setBeanName方法
// 4. 如果Bean实现了BeanFactoryAware接口, 调用setBeanFactory方法
// 5. 如果Bean实现了ApplicationContextAware接口, 调用setApplicationContext方法
// 6. 如果存在与Bean相关的BeanPostProcessors, 调用postProcessBeforeInitialization方法
// 7. 如果Bean实现了InitializingBean接口, 调用afterPropertiesSet方法
// 8. 如果Bean配置了init-method, 调用指定的初始化方法
// 9. 如果存在与Bean相关的BeanPostProcessors, 调用postProcessAfterInitialization方法
// 10. Bean现在可以使用了
// 11. 如果容器关闭, 如果Bean实现了DisposableBean接口, 调用destroy方法
// 12. 如果Bean配置了destroy-method, 调用指定的销毁方法言归正传,我们继续往下看。
Spring Bean 的生命周期的扩展点
前面我们可以看到关于Spring的生命周期和Java对象区别的回答时,里面还讲述了一些关于Aware接口和 BeanPostProcessors 等内容,这些具体的点实际就是与 生命周期的扩展点相关(不同阶段中间进行的活动)。
下面我们来讲述一下具体的扩展点使用。
Bean 自身的方法
在Bean的生命周期中,Bean自身是有一些特定方法是能够被调用的,以便完成其生命周期过程。
比如构造函数、getter/setter 以及 init-method 和 destory-method 所指定的方法等,而这些方法又分别对应着上文说的四个阶段:实例化、属性赋值、初始化和销毁。
这些Bean自身的方法一般是我们在配置Bean的时候就已经定义好的,
容器级别方法(BeanPostProcessor接口)
将这个容器级别方法理解为阶段中间容器会进行的一些操作,这些方法一般是 BeanPostProcessor 的一系列接口。
在上述讲到的Bean 四个阶段,在这四个阶段的执行过程中,进行一些前置或者后置的操作。
这些操作独立于 Bean 之外,并且会注册到 Spring 容器中,在Spring 容器创建Bean的时候,会进行一些处理。
工厂后处理器方法(BeanFactoryProcessor 接口)
工厂后处理器方法是用于来实现某些特定功能。
BeanFactoryPostProcessor是另一种容器级别的扩展点,它允许对Bean定义(BeanDefinition)进行读取和修改,这在Bean实例化之前执行。
Bean 级生命周期方法
Bean 级生命周期方法指的是针对 Bean 实例的个性化行为
Bean级生命周期方法是指直接在Bean类中实现的接口方法,这些方法针对特定Bean实例生效。包括:
- Aware接口:如
BeanNameAware、BeanFactoryAware、ApplicationContextAware等,允许Bean获取容器相关的资源和信息。 - InitializingBean和DisposableBean接口:分别用于自定义初始化后和销毁前的逻辑
通过直接在Bean类中实现这些接口,可以使Bean在其生命周期的特定时刻获得执行自定义逻辑的能力。
二、扩展点
2.1 Spring Bean 自身的方法使用
在Spring框架中,Bean的生命周期管理是通过一系列约定的方法来实现的,这些方法允许Spring容器在Bean的生命周期的不同阶段进行干预。以下是这些自身方法的详细说明,对应于Bean生命周期的四个主要阶段:实例化、属性赋值、初始化和销毁。
Bean 自身方法使用
- 实例化
- 构造函数(Constructor):是实例化阶段最基本的方法。Spring根据Bean的定义来调用相应的构造函数创建Bean实例。这可能是无参构造函数或带有参数的构造函数,后者用于依赖注入。
- 属性赋值
- Getter和Setter方法:用于属性赋值阶段。Spring通过反射调用Bean的Setter方法来注入依赖。这些方法遵循JavaBean的命名约定,例如,属性
name对应于getName()和setName(String name)。
- Getter和Setter方法:用于属性赋值阶段。Spring通过反射调用Bean的Setter方法来注入依赖。这些方法遵循JavaBean的命名约定,例如,属性
- 初始化
- 自定义初始化方法:可以在Bean定义中通过
init-method属性指定一个方法作为Bean的初始化方法。这个方法在属性赋值之后调用,用于执行任何必要的初始化逻辑。 - @PostConstruct注解::初始化之前调用的方法
- 自定义初始化方法:可以在Bean定义中通过
- 销毁
- 自定义销毁方法:与初始化方法类似,可以在Bean定义中通过
destroy-method属性指定一个方法作为Bean的销毁方法。当容器关闭时,这个方法被调用,用于执行任何必要的清理工作。 - @PreDestroy注解:Spring容器在销毁Bean之前调用这个方法。
- 自定义销毁方法:与初始化方法类似,可以在Bean定义中通过
具体使用示例
展示如何在Spring中使用Bean自身的方法:
package com.example;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class MyBean {
private String name;
// 构造函数
public MyBean() {
System.out.println("MyBean is being constructed without arguments.");
}
// 带参数的构造函数,用于依赖注入
public MyBean(String name) {
this.name = name;
System.out.println("MyBean is being constructed with name: " + name);
}
// Getter和Setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("Setting the name of MyBean to: " + name);
}
// 自定义初始化方法
public void myCustomInit() {
System.out.println("Custom init method of MyBean is called.");
}
// 使用@PostConstruct注解的初始化方法
@PostConstruct
public void postConstructInit() {
System.out.println("@PostConstruct init method is called.");
}
// 自定义销毁方法
public void myCustomDestroy() {
System.out.println("Custom destroy method of MyBean is called.");
}
// 使用@PreDestroy注解的销毁方法
@PreDestroy
public void preDestroyCleanup() {
System.out.println("@PreDestroy cleanup method is called.");
}
}接下来,在Spring配置文件或Java配置中,您需要注册这个Bean,并指定init-method和destroy-method:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myBean" class="com.example.MyBean" init-method="myCustomInit" destroy-method="myCustomDestroy">
<!-- 如果使用构造函数注入,可以如下配置 -->
<constructor-arg value="John Doe"/>
</bean>
</beans>或者使用Java配置:
package com.example.config;
import com.example.MyBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean(initMethod = "myCustomInit", destroyMethod = "myCustomDestroy")
public MyBean myBean() {
return new MyBean("John Doe");
}
}在该示例中,MyBean类展示了如何定义构造函数、getter和setter方法、自定义的初始化和销毁方法,以及如何使用@PostConstruct和@PreDestroy注解来自动执行初始化前和销毁前的逻辑。
通过在Spring配置中指定init-method和destroy-method属性,我们可以控制Spring何时调用这些方法,从而实现对Bean生命周期的精细管理。
2.2 容器级别方法
将这个容器级别方法理解为阶段中间容器会进行的一些操作,这些方法一般是 BeanPostProcessor 的一系列接口。
在上述讲到的Bean 四个阶段,在这四个阶段的执行过程中,进行一些前置或者后置的操作。
这些操作独立于 Bean 之外,并且会注册到 Spring 容器中,在Spring 容器创建Bean的时候,会进行一些处理。
BeanPostProcessor接口提供了容器级别的扩展点,允许在Bean的实例化和初始化前后插入自定义操作。这些操作包括:
- 实例化前后
- postProcessBeforeInstantiation
- postProcessAfterInstantiation
- 初始化前后
- postProcessBeforeInitialization:在任何Bean初始化回调(如
@PostConstruct注解的方法、afterPropertiesSet、自定义的init-method)之前调用。 - postProcessAfterInitialization:在所有Bean初始化回调之后调用。
- postProcessBeforeInitialization:在任何Bean初始化回调(如
通过实现BeanPostProcessor接口并注册为Spring容器的Bean,可以对所有Bean的实例化和初始化过程进行干预。
可以理解 InstantiationAwareBeanPostProcessor 接口方法是 作为 实例化阶段的"产前产后护理";BeanPostProcessor 是 初始化阶段的 “关键调整和增强”。
具体的一个关系看下图:

补充一点关于
InstantiationAwareBeanPostProcessor的描述以确保概念的完整性和准确性。
BeanPostProcessor接口和InstantiationAwareBeanPostProcessor接口的使用:
BeanPostProcessor:允许在Bean的初始化前后执行自定义逻辑。这包括:postProcessBeforeInitialization: 在Bean初始化之前调用(如调用@PostConstruct注解的方法、InitializingBean的afterPropertiesSet方法或自定义的init-method之前)。postProcessAfterInitialization: 在Bean初始化之后调用(如上述初始化方法执行之后)。
InstantiationAwareBeanPostProcessor:是BeanPostProcessor的一个扩展,提供了更多控制,包括:postProcessBeforeInstantiation: 在Bean实例化之前调用,允许返回一个代理对象来代替真正的实例。postProcessAfterInstantiation: 在Bean实例化之后、设置属性之前调用,允许对Bean实例进行额外的处理。
通过这些接口,Spring允许开发者在Bean生命周期的关键阶段介入,提供了极高的灵活性来定制Bean的行为,比如通过代理模式增强Bean、修改Bean属性、注入额外的依赖等。
这些特性使得Spring非常适合于企业级应用的开发,因为它们允许面向切面的编程(AOP)、事务管理等高级功能的实现。
示例:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在初始化之前执行的逻辑
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 在初始化之后执行的逻辑
return bean;
}
}通过注册上述BeanPostProcessor的实现类到Spring容器,可以实现对所有Bean实例化和初始化过程的自定义干预。
这不仅提高了代码的可维护性和可扩展性,也为实现复杂的业务逻辑提供了便利。
2.3 工厂后处理器方法
BeanFactoryProcessor 一系列接口
包括 AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor 等。
这些都是 Spring 框架中已经实现好的 BeanFactoryPostProcessor,用来实现某些特定的功能
BeanFactoryProcessor 接口 vs BeanPostProcessor接口
BeanFactoryPostProcessor 接口和 BeanPostProcessor 接口都是 Spring 框架中用于定制和扩展 Bean 的关键接口,但它们的作用和时机略有不同。
BeanFactoryPostProcessor 接口:
作用:
BeanFactoryPostProcessor接口用于在 Spring 容器实例化 Bean 之前修改或定制 BeanFactory 的配置。时机: 在 Spring 容器读取了 Bean 的定义(配置元数据)但在实例化任何 Bean 之前,
BeanFactoryPostProcessor接口提供了机会来修改 Bean 的定义,例如修改属性值、添加属性等。实现方法: 实现
postProcessBeanFactory方法,该方法传递了 BeanFactory 对象,可以在此方法中修改 BeanFactory 的配置。
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 在这里可以修改 BeanFactory 的配置
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 在这里可以注册新的 BeanDefinition
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);
registry.registerBeanDefinition("myBean", builder.getBeanDefinition());
}
}BeanPostProcessor 接口
作用:
BeanPostProcessor接口用于在 Spring 容器实例化 Bean 后,在 Bean 的初始化前后执行一些自定义的逻辑。时机: 当 Bean 被实例化后,但在调用其初始化方法(如果有的话)之前,
BeanPostProcessor提供了postProcessBeforeInitialization和postProcessAfterInitialization方法用于在初始化阶段进行定制操作。实现方法: 实现
BeanPostProcessor接口的两个方法,可以在这两个方法中添加定制逻辑。
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在初始化之前的逻辑
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 在初始化之后的逻辑
return bean;
}
}总结
BeanFactoryPostProcessor主要用于修改整个 BeanFactory 的配置,它在 Bean 实例化之前执行。BeanPostProcessor主要用于在每个 Bean 的初始化阶段添加自定义逻辑,它在 Bean 实例化后,初始化方法调用前后执行。
在实际应用中,可以同时使用这两个接口来完成更复杂的定制需求。
2.4 Bean 级生命周期方法
关于 Bean 级生命周期方法的理解:
- 这些方法提供了针对 Bean 实例的个性化行为,允许 Bean 在其生命周期的关键点做出响应。
通过这些方法,是可以对于某个Bean实例进行个性化操作的。
可以理解为 Bean 类直接实现接口的方法,比如 BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean、DisposableBean 等方法,这些方法只对当前 Bean 生效。
Aware 类型的接口
Aware 类型的接口的作用就是让我们能够拿到 Spring 容器中的一些资源。
基本都能够见名知意,Aware 之前的名字就是可以拿到什么资源,例如 BeanNameAware 可以拿到 BeanName,以此类推。
三、Spring Bean 详细生命周期
Spring 的生命周期基本上是很多面试的时候会遇到的一个问题,其中深度一些可能会问一下相关的源码实现;
这部分内容主要还是围绕IOC和AOP的一个实现源码的学习,以及如何实现的;如果有相关学习,并对此有所思考,可能是成为面试官比较亲耐的一个考查因素。
Bean 的生命周期
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值 利用 set() 方法设置一些属性值。
- 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName() 方法,传入 Bean 的名字。
- 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader() 方法,传入 ClassLoader 对象的实例。
- 如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanFactory() 方法,传入 BeanFactory 对象的实例。
- 与上面的类似,如果实现了其他 * .Aware 接口,就调用相应的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行 postProcessBeforeInitialization() 方法
- 如果 Bean 实现了 InitializingBean 接口,执行 afterPropertiesSet() 方法。
- 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行 postProcessAfterInitialization() 方法
- 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
- 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
Spring Bean生命周期详细回顾:
- 实例化Bean:Spring容器先通过构造器(或者对于FactoryBean来说是通过FactoryBean的
getObject()方法)来创建Bean实例。 - 填充属性:Spring容器把值和Bean的引用注入到Bean对应的属性中。
- 调用BeanNameAware的setBeanName()方法:如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法。
- 调用BeanFactoryAware的setBeanFactory()方法:如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入。
- 预初始化(@PostConstruct注解方法):通过Bean的postProcessBeforeInitialization()方法。
- 初始化:如果Bean实现了InitializingBean接口,Spring将调用其afterPropertiesSet()方法。此外,如果Bean在配置文件中定义了init-method属性,该方法也会被调用。
- 后初始化(BeanPostProcessor):通过Bean的postProcessAfterInitialization()方法,可以对Bean进行额外的处理。
- Bean准备就绪:此时,Bean已经准备好被应用中使用了,处于完全初始化状态。
- 销毁前(@PreDestroy注解方法):当容器关闭时,如果Bean实现了DisposableBean接口,Spring将调用其destroy()方法。同样,如果Bean使用了destroy-method声明了销毁方法,该方法也会被调用。
通过这个详细的生命周期,我们可以看到Spring在Bean的创建和销毁过程中提供了丰富的扩展点,使得我们可以根据需要插入自己的代码,进行自定义的处理。
四、源码解析
在我们讲到 IOC 的时候,它在Spring 框架的实际实现主要是依赖于BeanFactory接口及其子接口ApplicationContext。
IOC 的实现是比较复杂的一个过程,涉及到了很多组件和概念。
在前面的基础概念中,出现过 BeanDefinition、 BeanFactoryPostProcessor、 BeanPostProcessor 等词,这里对相关概念做一个小的总结。
to be contined...
这部分内容需要整合,是写的有点问题的,逻辑关联不强,重复性太高。
基础概念
BeanFactory接口
- 功能:
BeanFactory是Spring IoC容器的核心接口,它定义了IoC容器的基本功能,如获取bean、检查bean的存在等。 - 实现类:
XmlBeanFactory(已弃用)、DefaultListableBeanFactory等。
ApplicationContext接口
- 功能:
ApplicationContext是BeanFactory的子接口,提供了更完整的功能,比如国际化支持、事件传播等。它是Spring中最常用的IoC容器接口。 - 实现类:
ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、AnnotationConfigApplicationContext等。
BeanDefinition及其解析
- 功能:
BeanDefinition表示Spring IoC容器中管理的bean的定义信息,包括类名、作用域、生命周期回调等。 - 实现:Spring通过读取配置文件(XML、Java Config)解析bean定义,并将解析结果封装为
BeanDefinition对象。
BeanFactoryPostProcessor接口
- 功能:允许在容器实例化任何bean之前读取并修改bean的定义(即
BeanDefinition)。可以用于自定义修改bean定义的逻辑。 - 实现类:
PropertyPlaceholderConfigurer、CustomEditorConfigurer等。
BeanPostProcessor接口
- 功能:提供了修改新实例化的bean对象的扩展点,比如AOP代理的创建就是在这一步骤中实现的。
- 实现类:
AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor等。
- 依赖注入
- 功能:在bean的实例化过程中,Spring IoC容器会根据
BeanDefinition中的信息,通过反射等技术,自动将声明的依赖注入到bean中。 - 实现:主要通过
BeanWrapper实现属性的设置,AutowiredAnnotationBeanPostProcessor处理@Autowired注解等。
阅读链路
- 启动入口:从
ApplicationContext的实现类开始,了解容器的初始化过程。 - Bean定义的解析与注册:深入到如何解析配置(XML、注解)并将解析结果转换为
BeanDefinition,以及BeanDefinition是如何注册到容器中的。 - Bean的创建与依赖注入:探究容器是如何创建bean实例、完成依赖注入的。
- 生命周期管理:了解
BeanPostProcessor和BeanFactoryPostProcessor在bean生命周期中的作用。 - 高级特性:AOP、事件监听等高级特性是如何与IoC容器整合的。
相关概念回顾
Spring上下文
从代码级别来说,就是指Spring Context
从源码级别,我们初始化Spring Context的时候,一堆的Spring组件围绕在一起,使其能够正常工作,这个状态就被称为Spring环境。
Spring 初始化操作
具体操作可以见下#ClassPathXmlApplicationContext 的构造方法哪里会被加载并使用
使用前需要引入 spring-context 相关的依赖,初始化Bean可以通过注解的方式也可以通过xml的方式。
BeanFactory与ApplicationContext
先了解一下 BeanFactory 与 ApplicationContext 接口两个的作用与概念:
org.springframework.beans和org.springframework.context包是Spring Framework的IoC容器的基础。BeanFactory提供了配置框架和基本功能,提供了一种高级配置机制,能够管理任何类型的对象。ApplicationContext是BeanFactory的一个子接口,相比于BeanFactory来说,增加了更多的企业特定功能, 是BeanFactory的一个完整的超集。BeanFactory实现了延迟加载(懒加载),只有在请求获取Bean时(例如,通过getBean()方法),容器才会创建该Bean。这意味着如果应用中未使用某个Bean,它就不会被实例化。ApplicationContext其下管理的 Bean 是在IOC容器初始化的时候完成 Bean 实例化。
实例化 Instantiation
其中第一阶段 —— 实例化 Instantiation,
Bean 实例化的时机分为两种,一种是 BeanFactory,还有一种是 ApplicationContext;
下面是两者差别:
- BeanFactory
- 其下管理的Bean 在使用到Bean的时候 才会进行实例化Bean操作(懒加载策略)
- ApplicationContext
- 其下管理的 Bean 在IOC容器初始化的时候完成 Bean 实例化。
ApplicationContext是BeanFactory的子接口,复杂程度更高一些。- 如
AnnotationConfigApplicationContext和ClassPathXmlApplicationContext等,提供了多种方便的方式来创建ApplicationContext实例
ApplicationContext
org.springframework.context.ApplicationContext 接口代表Spring IoC容器,负责实例化、配置和组装bean。
AbstractApplicationContext
AbstractApplicationContext 实现了 ApplicationContext 接口,提供了这个接口的大部分通用功能。
它是实际应用上下文类(如 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext)的父类
通过继承和扩展 AbstractApplicationContext,Spring 允许开发者自定义应用上下文的行为,以满足特定的业务需求。
ClassPathXmlApplicationContext
ClassPathXmlApplicationContext 的构造方法哪里会被加载并使用?
以下是几个典型场景,其中可能会加载并使用 ClassPathXmlApplicationContext 的构造方法:
- Java 应用的主方法 (main)
在一个标准的 Java 应用程序中,你可以在 main 方法中创建 ClassPathXmlApplicationContext 的实例来启动 Spring 容器。这是最常见的用法。
public class MyApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 使用 context 获取 Bean 实例...
}
}在这个例子中,ClassPathXmlApplicationContext 用于加载名为 "applicationContext.xml" 的配置文件。
- Web 应用程序
在基于 Servlet 的传统 Web 应用程序中,可以在 Servlet 的 init 方法中创建 ClassPathXmlApplicationContext,或者使用 Spring 的 ContextLoaderListener 在 Web 应用启动时自动加载 Spring 上下文。
- 单元测试
在编写 Spring 应用的单元测试时,可以在测试类中创建 ClassPathXmlApplicationContext 来加载所需的 Spring 配置,并进行测试。
public class MyTest {
@Test
public void testSomeService() {
ApplicationContext context = new ClassPathXmlApplicationContext("testContext.xml");
MyService myService = context.getBean(MyService.class);
// 执行测试...
}
}在这里,测试使用了单独的配置文件 "testContext.xml"。
- Spring Boot 应用
使用 Spring Boot 时通常不直接使用 ClassPathXmlApplicationContext
Spring Boot 提供了基于注解的配置和自动配置的能力,一般是使用注解配置的方式进行声明Bean操作 ,但在一些旧的或特殊的情况下,可能仍然需要手动加载 XML 配置的方式。
容器级别方法
这部分内容待后续完善分析。
源码内容分析(容器级别方法)
需要去了解Bean的生命周期,这个源码对应的方法是必须去了解和看的。
InstantiationAwareBeanPostProcessor 接口分析
查看源码,可以看到 InstantiationAwareBeanPostProcessor 接口是继承 BeanPostProcessor
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessorBeanPostProcessor
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}AbstractAutowireCapableBeanFactory#createBean
// 创建Bean实例的方法,接收Bean的名称、RootBeanDefinition(Bean的定义信息)和参数数组
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// 如果启用了跟踪日志,输出创建Bean实例的跟踪信息
if (this.logger.isTraceEnabled()) {
this.logger.trace("Creating instance of bean '" + beanName + "'");
}
// 解析Bean的类信息,如果已经有解析过的类信息,使用之前解析得到的类信息
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
// 如果解析得到的类信息不为空,且当前Bean的定义信息没有指定类信息,则更新Bean的定义信息
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
// 准备处理方法的覆盖,即准备解析方法注解
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var9) {
// 如果方法注解解析失败,抛出BeanDefinitionStoreException异常
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
}
Object beanInstance;
try {
// 在实例化Bean之前,尝试调用BeanPostProcessor的beforeInstantiation方法
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
// 如果beforeInstantiation方法返回非空,表示已经创建了Bean实例,直接返回该实例
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var10) {
// 如果beforeInstantiation方法抛出异常,抛出BeanCreationException异常
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
}
try {
// 执行真正的Bean创建逻辑,包括实例化、属性注入等过程
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
// 如果启用了跟踪日志,输出Bean实例创建完成的跟踪信息
if (this.logger.isTraceEnabled()) {
this.logger.trace("Finished creating instance of bean '" + beanName + "'");
}
// 返回创建的Bean实例
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
// 如果Bean创建过程中出现了异常,抛出异常
throw var7;
} catch (Throwable var8) {
// 如果Bean创建过程中出现了未捕获的异常,抛出BeanCreationException异常
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
}
}Bean 创建流程入口 refresh()
Bean 创建流程入口
这里直接跟一下源码看一下相关内容
下面的代码是从 spring-context-5.2.4.RELEASE 版本中的 AbstractApplicationContext 抽象类下相关方法和内容说明。
在实际应用上下文类中(如 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext),他们的构造方法中会调用这个 refresh() 方法类进行初始化 Spring 容器。
因此可以判断出 Bean 创建流程入口 是定义在 AbstractApplicationContext 抽象类下 refresh() 方法。
refressh方法
这里实际看一下相关代码 AbstractApplicationContext#refresh()
public void refresh() throws BeansException, IllegalStateException {
// 同步锁确保容器刷新时的线程安全
synchronized (this.startupShutdownMonitor) {
// 准备刷新,设置启动日期和活跃状态等
this.prepareRefresh();
// 获取新的 BeanFactory,初始化 BeanFactory,并加载 Bean 定义
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 配置 BeanFactory,设置类加载器、事件处理器等
this.prepareBeanFactory(beanFactory);
try {
// 允许在 BeanFactory 标准初始化之后进行定制修改
this.postProcessBeanFactory(beanFactory);
// 调用在容器中注册的 BeanFactoryPostProcessor
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor,这些处理器影响所有 Bean 的创建
this.registerBeanPostProcessors(beanFactory);
// 初始化 MessageSource 组件,用于国际化处理
this.initMessageSource();
// 初始化 ApplicationEventMulticaster,用于事件广播
this.initApplicationEventMulticaster();
// 特定于 ApplicationContext 的刷新操作
this.onRefresh();
// 注册监听器到事件广播器
this.registerListeners();
// 初始化所有剩余的非懒加载单例
this.finishBeanFactoryInitialization(beanFactory);
// 完成刷新过程,通知生命周期处理器以及发布相应的事件
this.finishRefresh();
} catch (BeansException var9) {
// 在上下文初始化过程中捕获并处理异常
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
// 销毁已创建的 Bean,以防有些 Bean 已经初始化了,但后续的初始化过程失败了
this.destroyBeans();
// 取消刷新操作,重置上下文的同步标志
this.cancelRefresh(var9);
// 重新抛出异常,通知外部调用者
throw var9;
} finally {
// 重置公共缓存(例如 Reflection 缓存)
this.resetCommonCaches();
}
}
}可以看到初始化单例这步操作是在 this.finishBeanFactoryInitialization(beanFactory); 这里进行的
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 如果 BeanFactory 包含名为 "conversionService" 的 Bean,并且这个 Bean 适配于 ConversionService 类型
if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
// 将这个 Bean 设置为容器的 ConversionService
beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
}
// 如果 BeanFactory 还没有嵌入的值解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
// 添加一个嵌入的值解析器,用于解析占位符
beanFactory.addEmbeddedValueResolver(strVal -> {
return this.getEnvironment().resolvePlaceholders(strVal);
});
}
// 获取所有实现 LoadTimeWeaverAware 接口的 Bean 的名称
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
// 遍历这些 Bean 名称
for (String weaverAwareName : weaverAwareNames) {
// 初始化相应的 Bean,以确保它们能够执行加载时织入(Load Time Weaving)的相关逻辑
this.getBean(weaverAwareName);
}
// 将 BeanFactory 的临时类加载器设置为 null
beanFactory.setTempClassLoader(null);
// 冻结所有的 Bean 定义,表示注册的 Bean 定义将不再被修改或任何进一步的处理
beanFactory.freezeConfiguration();
// 预实例化单例,确保所有非懒加载的单例都被实例化
beanFactory.preInstantiateSingletons();
}五、视频学习
Spring Bean 的生命周期001
视频地址: https://www.bilibili.com/video/BV1584y1r7n6/
作为部分内容学习和回顾。

生产 → 使用 → 销毁
生产
启动,准备容器/环境等
① 加载 Bean 定义(BeanDefinitions)
加载Bean定义
run()
→
refreshContext()
→
refresh()
→
obtainFreshBeanFactory()
→
refreshBeanFactory()
→
loadBeanDefinitions()通过 loadBeanDefinitions 扫描所有xml配置、注解将Bean记录在 Bean定义集合 beanDefinitionMap 中
②创建 Bean 对象(createBean)
遍历“Bean定义”集合
通过 createBean 遍历 beanDefinitionMap 创建bean
创建Bean
run()
→
refreshContext()
→
refresh()
→
finishBeanFactoryInitialization()
→
preInstantiateSingletioins()
→
doGetBean()
→
createBean()2.1.构造对象
通过 createBeanInstance 方法进行对象的构造
使用反射机制从“Bean定义”中的BeanClass拿到类的构造方法
准备参数:在单例池中,根据参数的Class类进行查找
构造对象:通过反射进行Bean的构造(如果是无参则无需准备参数直接构造)
查找Class类 当匹配到多个实例, 会再根据参数名进行匹配
2.2.填充属性
通过 populateBean 方法对 Bean 内部所需属性进行属性填充, 通常是 @Autowired 注解的变量
三级缓存进行依赖注入
2.3.初始化实例
通过 initializeBean 方法对实例进行初始化
初始化操作:
- 初始化容器相关信息 通过 invokeAwareMethods 方法为实现各种 Aware 接口的Bean设置诸如 beanName, beanFactory 等容器信息 Aware 接口指代:信息感知接口
- 通过 invokeInitMethods 方法执行 Bean 的初始化方法
该 invokeInitMethods 方法是通过实现 InitializingBean 接口而实现的 afterPropertiesSet 方法 【Bean填充属性后执行】 ((InitializingBean)bean).afterPropertiesSet()
afterPropertiesSet
↓
init-Methods
↓
BeanPostProcessors销毁操作
- 销毁操作
- 销毁前
- 销毁之前会执行 postProcessBeforeDestruction "销毁前处理器“,这步会执行 Bean 中 @PreDestroy 注解的方法
- 容器销毁
- 后续通过 destoryBeans 方法逐一“销毁”容器中的Bean,销毁的时候会执行 destroy 方法(通过registerDisposableBean方法注册的Bean,该接口只有一个方法 destroy。
- 在Bean销毁的时候,Spring容器会调用这个方法。)
- Bean自定义销毁方法
- “客户销毁方法”invokeCustomDestroyMethod; → 执行Bean上自定义的 destoryMethod 方法
- 销毁前
附录
Spring Bean 生命周期流程图

参考
- https://docs.spring.io/spring-framework/reference/6.1-SNAPSHOT/core/beans.html
- https://springdoc.cn/spring/core.html#spring-core
- https://www.bilibili.com/video/BV1584y1r7n6
- https://javaguide.cn/system-design/framework/spring/spring-knowledge-and-questions-summary.html
- https://blog.csdn.net/riemann_/article/details/118500805
- https://blog.csdn.net/qq_20021569/article/details/109178816
- https://gitee.com/moxi159753/LearningNotes/tree/master/校招面试/Spring源码解析
- https://cloud.tencent.com/developer/article/2216932